﻿namespace Common.Helpers
{
    using System;
    using Common.Protocol;

    public static class TimeCounter
    {
        public static DateTime RemoveMilliseconds(DateTime currentTime, long milliseconds)
        {
            int currentBlockIndex = Protocol.FindBlockByTime(currentTime).Value;
            DateTime time = currentTime;

            for (int i = currentBlockIndex; i >= 0; i--)
            {
                Block currentBlock = Protocol.Blocks[i];
                long counter = (long)(milliseconds - (time - currentBlock.Start).TotalMilliseconds);
                if (counter < 0)
                {
                    time = time.AddTicks(-milliseconds * TimeSpan.TicksPerMillisecond);
                    break;
                }
                else
                {
                    if (i > 0)
                    {
                        time = Protocol.Blocks[i - 1].End;
                        milliseconds = counter;
                    }
                    else
                    {
                        return Protocol.Blocks[0].Start;
                    }
                }
            }

            if (time == currentTime)
            {
                return Protocol.Blocks[0].Start;
            }

            return time;
        }

        public static DateTime AddMilliseconds(DateTime currentTime, long milliseconds)
        {
            int currentBlockIndex = Protocol.FindBlockByTime(currentTime).Value;
            DateTime time = currentTime;

            for (int i = currentBlockIndex; i < Protocol.Blocks.Count; i++)
            {
                Block currentBlock = Protocol.Blocks[i];
                long counter = (long)(milliseconds - (currentBlock.End - time).TotalMilliseconds);
                if (counter < 0)
                {
                    time = time.AddTicks(milliseconds * TimeSpan.TicksPerMillisecond);
                    break;
                }
                else
                {
                    if (i + 1 < Protocol.Blocks.Count)
                    {
                        time = Protocol.Blocks[i + 1].Start;
                        milliseconds = counter;
                    }
                    else
                    {
                        return Protocol.Blocks[Protocol.Blocks.Count - 1].End;
                    }
                }
            }

            if (time == currentTime)
            {
                return Protocol.Blocks[Protocol.Blocks.Count - 1].End;
            }

            return time;
        }

        public static DateTime FindCoolTime(DateTime time, ChartScale scale)
        {
            while (time.Millisecond != 0)
            {
                time = time.AddMilliseconds(1);
            }

            switch (scale.StepMilliseconds)
            {
                case 1000:
                {
                    break;
                }
                case 5000:
                {
                    while (time.Second % 5f != 0)
                    {
                        time = time.AddSeconds(1);
                    }

                    break;
                }
                case 15000:
                {
                    while (time.Second % 15f != 0)
                    {
                        time = time.AddSeconds(1);
                    }

                    break;
                }
                case 30000:
                {
                    while (time.Second != 0 && time.Second != 30)
                    {
                        time = time.AddSeconds(1);
                    }

                    break;
                }
                case 60000:
                {
                    while (time.Second != 0)
                    {
                        time = time.AddSeconds(1);
                    }

                    break;
                }
                case 25 * 6000:
                {
                    while (time.Second != 0 && time.Second != 30)
                    {
                        time = time.AddSeconds(1);
                    }

                    break;
                }
                case 10 * 60000:
                {
                    while (time.Second != 0)
                    {
                        time = time.AddSeconds(1);
                    }

                    while (time.Minute % 10f != 0)
                    {
                        time = time.AddMinutes(1);
                    }

                    break;
                }
                case 15 * 60000:
                {
                    while (time.Second != 0)
                    {
                        time = time.AddSeconds(1);
                    }

                    while (time.Minute % 15f != 0)
                    {
                        time = time.AddMinutes(1);
                    }

                    break;
                }
                case 30 * 60000:
                {
                    while (time.Second != 0)
                    {
                        time = time.AddSeconds(1);
                    }

                    while (time.Minute % 30f != 0)
                    {
                        time = time.AddMinutes(1);
                    }

                    break;
                }
            }

            return time;
        }

        public static DateTime FirstCompletePeriodStart(DateTime intervalStart, DateTime blockStart, int period)
        {
            DateTime time = blockStart;
            while (time < intervalStart)
            {
                time = time.AddMilliseconds(period);
            }

            return time;
        }

        public static DateTime LastCompletePeriodStart(DateTime intervalEnd, DateTime blockStart, int period)
        {
            DateTime time = blockStart;
            while (time < intervalEnd)
            {
                time = time.AddMilliseconds(period);
            }

            return time.AddTicks(-period * TimeSpan.TicksPerMillisecond);
        }
    }
}